import java.util.*;

import javax.swing.*;
import java.awt.*;

public class BasicTower extends Tower{
	
	public int[] colours;
	public int count = 0;
	
	public BasicTower(double X,double Y){
		super(X,Y);
	}
	public BasicTower(){
		super();
	}
	public void initBody(){
/*		double[][] Xcords = {
		{-26.0, -12.0, -1.0, 9.0, 25.0, 10.0, 24.0, 5.0, -1.0, -11.0, -25.0, -15.0},
		{35.0, 24.0, 33.0, 41.0},
		{23.0, 20.0, 31.0, 35.0},
		{-8.0, -2.0, 5.0, -3.0},
		{-36.0, -25.0, -25.0, -39.0},
		{-26.0, -40.0, -48.0, -38.0},
		{-24.0, -37.0, -35.0, -23.0},
		{-5.0, -13.0, -6.0, 0.0},
		{18.0, 12.0, 25.0, 29.0 }
		};
		double[][] Ycords = {
		{-12.0, -26.0, -16.0, -28.0, -12.0, -4.0, 10.0, 23.0, 8.0, 23.0, 9.0, -2.0},
		{-10.0, -1.0, 7.0, -3.0},
		{-38.0, -24.0, -26.0, -39.0},
		{-37.0, -29.0, -38.0, -50.0},
		{-26.0, -24.0, -38.0, -39.0},
		{-3.0, -11.0, 0.0, 5.0},
		{19.0, 19.0, 29.0, 28.0},
		{22.0, 33.0, 36.0, 28.0 },
		{20.0, 30.0, 32.0, 20.0}
		};
		double[][] Xcords = {{10,10,-10,-10}};
		double[][] Ycords = {{10,-10,-10,10}};
		int[][] colours = {{255,0,0}, {255,255,255},{150,150,150},{255,255,255},{150,150,150},{255,255,255},{150,150,150},{255,255,255},{150,150,150}};
		for(int i = 0; i < Xcords.length; i++){
			addBody(colours[i][0],colours[i][1],colours[i][2], Xcords[i],Ycords[i]);
		}
		grow(2);*/
	}
	
	public void initBodyColor(){
		double[][] Xcords = {{10,10,-10,-10}};
		double[][] Ycords = {{10,-10,-10,10}};
		for(int i = 0; i < Xcords.length; i++){
			addBody(colours[0],colours[1],colours[2], Xcords[i],Ycords[i]);
		}
	}
	
	public void initTurret(){
/* 		double[][] Xcords = {
 		{-1.0, -8.0, -1.0, 5.0 },
 		{-8.0, -25.0, -9.0, -16.0},
 		{4.0, 10.0, 6.0, 24.0},
 		{-22.0, -3.0, 16.0, -1.0}
 		};
		double[][] Ycords = {
		{-20.0, -14.0, 174.0, -13.0},
		{157.0, -15.0, -27.0, -13.0 },
		{-29.0, -16.0, 156.0, -20.0},
		{-29.0, -33.0, -32.0, -45.0}
		};
		int[][] colours = {{0,0,0},{155,155,155},{155,155,155},{255,0,0}};
		for(int i = 0; i < Xcords.length; i++){
			addTurret( colours[i][0],colours[i][1],colours[i][2], Xcords[i],Ycords[i]);

		}
		rotateTurret(-Math.PI/2.0);
		for(Poly i: turret){
			i.grow(0.5);
		}	  */		
	}
	public void initStats(){
		 hp=500; // hit points
		 ap=15; // attack power
		 range=100; // range of the unit's attack
		 vx=0; // velocity in the x direction
		 vy=0; // velocity in the y direction
		 v=0; // velocity
		 heat = 20;
		 bulletRad = 10;
		 rand = 25;
	}
	
	public void initStats(BasicTower bt){
		 hp=bt.hp; // hit points
		 ap=bt.ap; // attack power
		 range=bt.range; // range of the unit's attack
		 vx=bt.vx; // velocity in the x direction
		 vy=bt.vy; // velocity in the y direction
		 v=bt.vx; // velocity
		 bulletRad = bt.bulletRad;
		 rand = bt.rand;
		 cost = bt.cost;
	}
	
	public void produce(double x,double y){
		BasicTower tmp = new BasicTower(x,y);
		tmp.init(units,tower,grid,weapons,effects);
		tmp.initStats(this);
        for(WeaponComponent wh: weaponComponentList){
        	tmp.weaponComponentList.add(wh.clone());
        }
        tmp.colours = colours;
        tmp.initBodyColor();
		tower.add( tmp );
		count++;
	}
	public void attack(Unit enemy){
		for(WeaponComponent wc:weaponComponentList){
			long currentTime = System.currentTimeMillis();
			if(currentTime-wc.lasttime >= wc.heat*1000){
				wc.lasttime = currentTime;
				if(wc.name ==Global.SingleAttack){
					fireX = enemy.getX () ;
					fireY = enemy.getY () ;
					weapons.add ( new SingleAttack(effects,enemy,pos[0],pos[1],enemy.getX(),enemy.getY(),bulletRad,ap));
					//weapons.add ( new Transmit(effects,enemy,pos[0]+Global.randint(box[0]*-1,box[0]),pos[1]+Global.randint(box[0]*-1,box[0]),enemy.getX(),enemy.getY(),bulletRad,ap));	
				}
				if(wc.name ==Global.Laser){
					double tmpdamage = wc.attackdamage;
					fireX = enemy.getX () ;
					fireY = enemy.getY () ;
					LinkedList<Unit> tmpallTargets = (LinkedList<Unit>) units.clone();
					Collections.sort(tmpallTargets, new UnitHighComparator());
					Iterator<Unit> m = tmpallTargets.iterator() ;
					int index = tmpallTargets.indexOf(target);
					if(index==-1)
						continue;
				//	weapons.add ( new Laser(effects,enemy,pos[0],pos[1],enemy.getX(),enemy.getY(),bulletRad,ap));
					//weapons.add ( new Transmit(effects,enemy,pos[0]+Global.randint(box[0]*-1,box[0]),pos[1]+Global.randint(box[0]*-1,box[0]),enemy.getX(),enemy.getY(),bulletRad,ap));
					double nextX = pos[0];
					double nextY = pos[1];
					int count = 0;
					for(int i = index; i<tmpallTargets.size()&&count<3;i++){
						Unit n = tmpallTargets.get(i);
						weapons.add( new Laser(effects,n,nextX,nextY,n.getX(),n.getY(),bulletRad,tmpdamage));
						tmpdamage *=0.6;
						nextX = n.getX() ;
						nextY = n.getY() ;
						count++ ;
					}		
				}
				else if(wc.name ==Global.Transmit){
					fireX = enemy.getX () ;
					fireY = enemy.getY () ;
					Iterator<Unit> m = allTargets.iterator() ;
					int i = (new Random()).nextInt(allTargets.size());
					Unit n = allTargets.get(i);
				//	weapons.add ( new Transmit(effects,enemy,pos[0]+Global.randint(box[0]*-1,box[0]),pos[1]+Global.randint(box[0]*-1,box[0]),enemy.getX(),enemy.getY(),bulletRad,ap));
					double nextX = enemy.getX() ;
					double nextY = enemy.getY() ;
					weapons.add( new Transmit(effects,n,nextX+Global.randint(box[0]*-1,box[0]),nextY+Global.randint(box[0]*-1,box[0]),n.getX(),n.getY(),bulletRad,wc.attackdamage));
				}
				else if(wc.name ==Global.Seckilling){
					fireX = enemy.getX () ;
					fireY = enemy.getY () ;
					Iterator<Unit> m = allTargets.iterator() ;
					int i = (new Random()).nextInt(allTargets.size());
					Unit n = allTargets.get(i);
				//	weapons.add ( new Transmit(effects,enemy,pos[0]+Global.randint(box[0]*-1,box[0]),pos[1]+Global.randint(box[0]*-1,box[0]),enemy.getX(),enemy.getY(),bulletRad,ap));
					double nextX = enemy.getX() ;
					double nextY = enemy.getY() ;
					weapons.add( new Seckilling(effects,n,nextX+Global.randint(box[0]*-1,box[0]),nextY+Global.randint(box[0]*-1,box[0]),n.getX(),n.getY(),bulletRad,ap));
				}
				
				else if(wc.name ==Global.Dot){
					Dot dot = new Dot(effects,target,nextX+Global.randint(box[0]*-1,box[0]),nextY+Global.randint(box[0]*-1,box[0]),target.getX(),target.getY(),bulletRad,ap);
					dot.damage = wc.dotdamage;
					dot.dottimer = wc.dottimer;
					weapons.add(dot);
				}
				else if(wc.name ==Global.Freeze){
					Freeze freeze = new Freeze(effects,target,nextX+Global.randint(box[0]*-1,box[0]),nextY+Global.randint(box[0]*-1,box[0]),target.getX(),target.getY(),bulletRad,ap);
					freeze.freezetimer = wc.freeze;
					weapons.add(freeze);
				}
			}
		}
	}
	
	private  class UnitHighComparator implements  Comparator<Unit>{
		public int compare(Unit o1, Unit o2) {
			if(o1.currentPathNodeIndex<o2.currentPathNodeIndex)
				return 1;
			else if(o1.currentPathNodeIndex>o2.currentPathNodeIndex)
				return -1;
			return 0;
		}
	}
	
	public ArrayList<String> generateTowerInfo(){
		ArrayList<String> towerInfoList = new ArrayList<String>();
		String info = "$" + cost + " AP: " + (new java.text.DecimalFormat("0.0").format(ap)) + " Range: " + (int)range;
		towerInfoList.add(info);
		for(WeaponComponent wc: weaponComponentList){
			if(wc.name ==Global.SingleAttack){
				info = "SingleAttack " + " cd: " + new java.text.DecimalFormat("0.0").format(wc.heat)+ "s";
				towerInfoList.add(info);
			}
			else if(wc.name ==Global.Laser){
				info = "Laser " + " cd: " + new java.text.DecimalFormat("0.0").format(wc.heat)+ "s";
				towerInfoList.add(info);
			}
			else if(wc.name ==Global.Transmit){
				info = "Transmit " + " cd: " + new java.text.DecimalFormat("0.0").format(wc.heat)+ "s";
				towerInfoList.add(info);
			}
			else if(wc.name ==Global.Seckilling){
				info = "Seckilling " + " cd: " + new java.text.DecimalFormat("0.0").format(wc.heat)+ "s";
				towerInfoList.add(info);
			}
			else if(wc.name ==Global.Dot){
				info = "Dot " + " cd: " + new java.text.DecimalFormat("0.0").format(wc.heat) + "s" + " Damage: " + new java.text.DecimalFormat("0.0").format(wc.dotdamage);
				towerInfoList.add(info);
			}
			else if(wc.name ==Global.Freeze){
				info = "Freeze " + " Cooldown: " + new java.text.DecimalFormat("0.0").format(wc.heat)+ "s" +" Duration: " +  new java.text.DecimalFormat("0.0").format(wc.freeze);
				towerInfoList.add(info);
			}
		}
		return towerInfoList;
	}
}
